package com.wtwd.device.service.impl;


import com.wtwd.device.constant.AppMsgEnum;
import com.wtwd.device.constant.Constant;
import com.wtwd.device.constant.RespCode;
import com.wtwd.device.dao.FriendRecordMapper;
import com.wtwd.device.model.dto.ReplyAddFriendDto;
import com.wtwd.device.model.entity.*;
import com.wtwd.device.model.vo.*;
import com.wtwd.device.service.*;
import com.wtwd.device.util.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 表服务实现类
 *
 * @author mjy
 * @since 2021-09-16 13:24:14
 */
@Service
public class FriendRecordServiceImpl implements FriendRecordService {
    /**
     * 一天的时间戳
     */
    private Long oneTime = 86400000L;

    @Resource
    private FriendRecordMapper friendRecordMapper;

    @Resource
    private FriendRequestsService friendRequestsService;

    @Resource
    private AppUserInfoService appUserInfoService;

    @Resource
    private AppUserService appUserService;

    @Resource
    private StepService stepService;

    @Resource
    private AppDeviceService deviceService;

    @Resource
    private HeartRateService heartRateService;

    @Resource
    private BloodPressureRecordService bloodPressureRecordService;

    @Resource
    private BloodOxygenRecordService bloodOxygenRecordService;

    @Resource
    private SleepRecordService sleepRecordService;

    @Autowired
    private AppDeviceBloodOxygenTotalService appDeviceBloodOxygenTotalService;

    @Autowired
    private AppDeviceHeartRateTotalService appDeviceHeartRateTotalService;

    @Autowired
    private AppDeviceSleepRecordService appDeviceSleepRecordService;

    @Autowired
    private ILocationDataService locationDataService;


    @Autowired
    private ILastLocationDataService lastLocationDataService;


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public FriendRecord queryById(Long id) {
        return friendRecordMapper.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param friendRecord 筛选条件
     * @param pageRequest  分页对象
     * @return 查询结果
     */
    @Override
    public Page<FriendRecord> queryByPage(FriendRecord friendRecord, PageRequest pageRequest) {
        long total = friendRecordMapper.count(friendRecord);
        return new PageImpl<>(this.friendRecordMapper.queryAllByLimit(friendRecord, pageRequest), pageRequest, total);
    }

    /**
     * 新增数据
     *
     * @param friendRecord 实例对象
     * @return 实例对象
     */
    @Override
    public FriendRecord insert(FriendRecord friendRecord) {
        friendRecordMapper.insert(friendRecord);
        return friendRecord;
    }

    /**
     * 修改数据
     *
     * @param friendRecord 实例对象
     * @return 实例对象
     */
    @Override
    public FriendRecord update(FriendRecord friendRecord) {
        friendRecordMapper.update(friendRecord);
        return this.queryById(friendRecord.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return friendRecordMapper.deleteById(id) > 0;
    }


    /**
     * 添加好友之后用户的回复
     *
     * @param replyAddFriendDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultVO replyAddFriend(ReplyAddFriendDto replyAddFriendDto) {
        //校验用户是否属于同一app
        ResultVO resultVO = checkAppUserInfoType(replyAddFriendDto.getFriendId(), replyAddFriendDto.getUserId());
        if (RespCode.SUCCESS.getCode() != resultVO.getCode()) {
            return resultVO;
        }
        //更新消息状态
        Integer a = friendRequestsService.updateFriendRequestStatus(replyAddFriendDto.getType(), replyAddFriendDto.getId(), new Date().getTime());
        if (replyAddFriendDto.getType() == Constant.FRIEND_STATE_AGREE) {//如果是同意添加好友的状态
            String friendName = this.getUserName(replyAddFriendDto.getFriendId());
            String userName = this.getUserName(replyAddFriendDto.getUserId());
            if (StringUtils.isBlank(userName) || StringUtils.isBlank(friendName)) {
                return ResultVO.error(RespCode.USER_EXCEPTION);
            }
            //同意添加好友双向操作
            ArrayList<FriendRecord> recordArrayList = new ArrayList<>();
            //以自己为主,将对方添加成自己的好友
            FriendRecord userRecord = new FriendRecord();
            userRecord.setUserId(replyAddFriendDto.getUserId());
            userRecord.setFriendId(replyAddFriendDto.getFriendId());
            userRecord.setFriendNickname(friendName);
            recordArrayList.add(userRecord);
            //以对方为主将自己添加为好友
            FriendRecord friendRecord = new FriendRecord();
            friendRecord.setUserId(replyAddFriendDto.getFriendId());
            friendRecord.setFriendId(replyAddFriendDto.getUserId());
            friendRecord.setFriendNickname(userName);
            recordArrayList.add(friendRecord);
            Integer rest = friendRecordMapper.insertBatch(recordArrayList);
            //回复添加好友成功后检测自己在在对方申请阶段有无申请对方为好友,有的话同步申请记录为成功(处于申请中的记录只会有一条)
            if (rest > 0) {
                FriendRequests requests = friendRequestsService.getApplyFriendRequestByProposerAndRespondent(replyAddFriendDto.getUserId(), replyAddFriendDto.getFriendId());
                if (requests != null) {
                    Integer b = friendRequestsService.updateFriendRequestStatus(replyAddFriendDto.getType(), requests.getId(), new Date().getTime());
                    if (b <= 0) {
                        return ResultVO.error(RespCode.SYNCHRONOUS_FRIEND_FAIL);
                    }
                }
                return ResultVO.success();
            } else {
                return ResultVO.error();
            }
        } else if (replyAddFriendDto.getType() == Constant.FRIEND_STATE_REFUSE) {//拒绝(推送消息给好友)
            Map<String, Object> pushUserMap = this.getPushUserMap(replyAddFriendDto.getFriendId());
            if (pushUserMap == null) {
                return ResultVO.error(RespCode.UNINITIALIZED_APP_USER_INFO);
            }
            String name = (String) pushUserMap.get("name");
            String clientType = (String) pushUserMap.get("clientType");
            return appUserInfoService.pushTemplateMsgToAppUser(replyAddFriendDto.getFriendId(), clientType, AppMsgEnum.REFUSED_FRIEND, name);
        }
        if (a > 0) {
            return ResultVO.success();
        } else {
            return ResultVO.error();
        }
    }

    @Override
    public Integer updateFriendNickname(Long userId, Long friendId, String friendName) {
        return friendRecordMapper.updateFriendNickname(userId, friendId, friendName);
    }

    @Override
    public List<FriendVo> getFriendList(Long userId, Integer currentPage, Integer pageSize) {
        Integer start = currentPage * pageSize;
        //获取昨日时间
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        String yesterday = new SimpleDateFormat("yyyy-MM-dd ").format(cal.getTime());
        Long startTime = DateUtils.stringToTimestamp(yesterday, DateUtils.dateFormat18);
        Long endTime = startTime + oneTime;
        List<FriendVo> friendRecords = friendRecordMapper.getFriendList(userId, start, pageSize, startTime,endTime);
        return friendRecords;
    }

    @Override
    public FriendHealthFileVo getFriendFile(long friendId, String time) {
        //根据用户id获取用户绑定的设备
        Device device = deviceService.getDeviceByUserId(friendId);
        FriendHealthFileVo friendHealthFileVo = new FriendHealthFileVo();
//        FriendFileVo friendFileVo = new FriendFileVo();
//        if (device != null) {
////            //获取步数信息(此处数据精确到具体某一天,只会有一条)
////            Step step = stepService.getStepInfoByDeviceIdAndTime(device.getId(), time);
////            //获取心率数据(此处数据精确到具体某一天,只会有一条)
////            HeartRateRecord heartRateRecord = heartRateService.getHeartRateByDeviceIdAndTime(device.getId(), time);
////            //获取血压数据
////            BloodPressureRecord bloodPressureRecord = bloodPressureRecordService.getBloodPressureRecordByDeviceIdAndTime(device.getId(), time);
////            //血氧数据信息
////            BloodOxygenRecord bloodOxygenRecord = bloodOxygenRecordService.getBloodOxygenRecordByDeviceIdAndTime(device.getId(), time);
////            //睡眠数据信息
////            SleepRecord sleepRecord = sleepRecordService.getSleepRecordByDeviceIdAndTime(device.getId(), time);
////            friendFileVo.setStep(step);
////            friendFileVo.setHeartRateRecord(heartRateRecord);
////            friendFileVo.setBloodPressureRecord(bloodPressureRecord);
////            friendFileVo.setBloodOxygenRecord(bloodOxygenRecord);
////            friendFileVo.setSleepRecord(sleepRecord);
////        }
        if(device != null){
            BloodOxygenVo bloodOxygenVo = appDeviceBloodOxygenTotalService.selectBloodOxygenByTime(device.getId(),time);
            HeartRateVo heartRateVo = appDeviceHeartRateTotalService.selectHeartRateByTime(device.getId(), time);
            DeviceSleepRecordVo dayDeviceSleepByTime = appDeviceSleepRecordService.getDayDeviceSleepByTime(device.getId(), time);
            SleepVo sleepVo = new SleepVo();
            if(dayDeviceSleepByTime != null){
                sleepVo.setSeleepTime(dayDeviceSleepByTime.getDeepSleepLen() + dayDeviceSleepByTime.getLightSleepLen());
            }
//            LocationDataVo locationDataVo = locationDataService.getNewDeviceLocationByTime(device.getId(), time);
            LastLocationData locationDataVo = lastLocationDataService.getLastLocationDataByDeviceId(device.getId());
            friendHealthFileVo.setBloodOxygenVo(bloodOxygenVo);
            friendHealthFileVo.setHeartRateVo(heartRateVo);
            friendHealthFileVo.setSleepVo(sleepVo);
            friendHealthFileVo.setLastLocationData(locationDataVo);
        }
        return friendHealthFileVo;
    }

    @Override
    public ResultVO checkFriendRequests(FriendRequests friendRequests) {
        if (friendRequests.getProposer() == null || friendRequests.getRespondent() == null) {//校验参数
            return ResultVO.error(RespCode.PARAMS_ERROR);
        }
        //数据隔离(haifit的用户不能添加h-fit用户为好友)
        ResultVO resultVO = checkAppUserInfoType(friendRequests.getProposer(), friendRequests.getRespondent());
        if (RespCode.SUCCESS.getCode() != resultVO.getCode()) {
            return resultVO;
        }
        //鉴别好友是否添加
        FriendRecord friendOne = friendRecordMapper.getFriendOne(friendRequests.getRespondent(), friendRequests.getProposer());
        if (friendOne != null) {
            return ResultVO.error(RespCode.ALREADY_GOOD_FRIENDS);
        }
        //鉴别该好有记录是否已经处于申请中,如果处于申请中不重复添加提交申请
        FriendRequests selectFriend = new FriendRequests();
        selectFriend.setProposer(friendRequests.getProposer());
        selectFriend.setRespondent(friendRequests.getRespondent());
        List<FriendRequests> friendRequestsList = friendRequestsService.getFriendRequestByConditions(selectFriend);
        if (friendRequestsList != null || friendRequestsList.size() > 0) {
            //处于申请状态中(拒绝可再次提交申请)
            List<FriendRequests> collect = friendRequestsList.stream().filter(e -> e.getState().equals(1)).collect(Collectors.toList());
            if (collect != null && collect.size() > 0) {
                return ResultVO.error(RespCode.FRIEND_APPLY_STATE);
            }
        }
        return ResultVO.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespEntity deleteFriend(Long friendId, Long userId) {
        RespEntity respEntity = checkFriend(friendId, userId);
        if (RespCode.SUCCESS.getCode() != respEntity.getCode()) {
            return respEntity;
        }
        //删除好友之前获取用户名称用于推送
        String userName = this.getUserName(friendId);
        if (userName == null) {
            return new RespEntity(RespCode.UNINITIALIZED_APP_USER_INFO);
        }
        //删除好友双向删除
        Integer rest = friendRecordMapper.deleteByUserIdAndFriendId(userId, friendId);
        if (rest > 0) {
            Integer a = friendRecordMapper.deleteByUserIdAndFriendId(friendId, userId);
            if (a > 0) {//双方删除执行成功执行推送(推送给好友取消关注通知)
                Map<String, Object> pushUserMap = this.getPushUserMap(friendId);
                if (pushUserMap == null) {
                    return new RespEntity(RespCode.UNINITIALIZED_APP_USER_INFO);
                }
                String name = (String) pushUserMap.get("name");
                String clientType = (String) pushUserMap.get("clientType");
                appUserInfoService.pushTemplateMsgToAppUser(friendId, clientType, AppMsgEnum.DELETE_FRIEND, name);
            }
        }
        return new RespEntity(rest > 0 ? RespCode.SUCCESS : RespCode.FAIL);
    }

    /**
     * 校验双方是否已经是好友
     *
     * @param friendId
     * @param userId
     * @return
     */
    private RespEntity checkFriend(Long friendId, Long userId) {
        FriendRecord friendRecord = friendRecordMapper.getFriendOne(friendId, userId);
        if (friendRecord == null) {
            return new RespEntity(RespCode.NOT_FRIEND);
        }
        return new RespEntity(RespCode.SUCCESS);
    }


    /**
     * 检验用户是否属于同一App
     *
     * @param proposerId
     * @param respondentId
     * @return
     */
    public ResultVO checkAppUserInfoType(Long proposerId, Long respondentId) {
        //校验用户是否属于同一类型用户(此处没有in查的原因在于，我确定数据只会查这两次，且in会导致索引失效)
        AppUserInfo proposerInfo = appUserInfoService.getAppUserInfoByUserId(proposerId);
        AppUserInfo respondentInfo = appUserInfoService.getAppUserInfoByUserId(respondentId);
        if (proposerInfo == null || respondentInfo == null) {
            return ResultVO.error(RespCode.UNINITIALIZED_APP_USER_INFO);
        }
        if (!proposerInfo.getUserType().equals(respondentInfo.getUserType())) {
            return ResultVO.error(RespCode.UNIDENTIFICATION_USER);
        }
        return ResultVO.success();
    }

    /**
     * 获取用户的名称()
     * 查询好友名称，同步别名,当好友没有设置名称时,以手机号或者邮箱号作为别名
     * 没有连表查是为解决不同app用户要添加相应的if else
     *
     * @param userId
     * @return
     */
    private String getUserName(Long userId) {
        String name = "";
        AppUser user = appUserService.getUserByUserId(userId);
        if (user == null) {
            return name;
        }
        AppUserInfo userInfo = appUserInfoService.getAppUserInfoByUserId(userId);
        if (userInfo == null) {
            return name;
        }
        if (StringUtils.isNotBlank(userInfo.getName())) {
            name = userInfo.getName();
        } else if (StringUtils.isNotBlank(user.getPhone())) {
            name = user.getPhone();
        } else if (StringUtils.isNotBlank(user.getEmail())) {
            name = user.getEmail();
        } else {
            name = Constant.DEFAULT_USER_NAME;
        }
        return name;
    }


    /**
     * 获取用户的名称和该用户的客户端类型
     * 查询好友名称，同步别名,当好友没有设置名称时,以手机号或者邮箱号作为别名
     * 没有连表查是为解决不同app用户要添加相应的if else
     * 如果是手机号模糊处理中间字符串
     * 如果是邮箱模糊处理邮箱最后一个@符号前，中间字符串模糊
     *
     * @param userId
     * @return
     */
    @Override
    public Map<String, Object> getPushUserMap(Long userId) {
        HashMap<String, Object> map = new HashMap<>();
        AppUser user = appUserService.getUserByUserId(userId);
        if (user == null) {
            return map;
        }
        AppUserInfo userInfo = appUserInfoService.getAppUserInfoByUserId(userId);
        if (userInfo == null) {
            return map;
        }
        String name = "";
        if (StringUtils.isNotBlank(userInfo.getName())) {
            name = userInfo.getName();
        } else if (StringUtils.isNotBlank(user.getPhone())) {
            name = dealStringPhone(user.getPhone());
        } else if (StringUtils.isNotBlank(user.getEmail())) {
            name = dealStringEmail(user.getEmail());
        } else {
            name = Constant.DEFAULT_USER_NAME;
        }
        map.put("name", name);
        map.put("clientType", userInfo.getClientId());
        return map;
    }


    /**
     * 模糊处理手机号
     * 模糊位数字符串的一半(基数位向下取整)
     * 小于等于两位不处理
     *
     * @param phone
     * @return
     */
    private static String dealStringPhone(String phone) {
        if (StringUtils.isBlank(phone) || phone.length() <= 2) {
            return phone;
        }
        StringBuffer str = new StringBuffer(phone);
        //1.得到字符串模糊位数(向下取整)
        int num = str.length() / 2;
        //2.得到替换的起始位置(由中间位置,向前在推一个中间位置的一半)
        int index = num - (num / 2);
        //3.得到替换的末尾位置
        int end = index + num;
        //制作替换字符串
        StringBuilder replaceStr = new StringBuilder();
        for (int i = 0; i < num; i++) {
            replaceStr.append(Constant.STR_REPLACE);
        }
        StringBuffer replace = str.replace(index, end, replaceStr.toString());
        return replace.toString();
    }


    /**
     * 邮箱只处理最后一个@符之前的串，后面的串不参加处理
     * 其他处理同于手机号
     *
     * @param email
     * @return
     */
    private static String dealStringEmail(String email) {
        if (StringUtils.isBlank(email) || email.length() <= 2) {
            return email;
        }
        int endStr = email.lastIndexOf(Constant.EMAIL_FLAG);
        //存留后缀
        String dealEmailSuffix = email.substring(endStr);
        String dealEmailPrefix = email.substring(0, endStr);
        StringBuffer str = new StringBuffer(dealEmailPrefix);
        //1.得到字符串模糊位数(向下取整)
        int num = str.length() / 2;
        //2.得到替换的起始位置(由中间位置,向前在推一个中间位置的一半)
        int index = num - (num / 2);
        //3.得到替换的末尾位置
        int end = index + num;
        //制作替换字符串
        StringBuilder replaceStr = new StringBuilder();
        for (int i = 0; i < num; i++) {
            replaceStr.append(Constant.STR_REPLACE);
        }
        //处理完毕加上后缀
        StringBuffer replace = str.replace(index, end, replaceStr.toString()).append(dealEmailSuffix);
        return replace.toString();
    }


}


